#pragma once
#ifndef __TESTBLOCK__H__
#define __TESTBLOCK__H__

#include "ATTest.h"

static const UInt32 ROW_NINE = 9;

class BlockTestCase : public TestCase
{
public:
	BlockTestCase(const Char* pszName) : TestCase(pszName)
	{
		Add(NEW_TEST(BlockTestCase::TestRowBlock));
		Add(NEW_TEST(BlockTestCase::TestModifyCellValue));
		Add(NEW_TEST(BlockTestCase::TestDuplicatedIndex));
		Add(NEW_TEST(BlockTestCase::TestFindCell));
		Add(NEW_TEST(BlockTestCase::TestIsValid));
	}

	virtual Bool SetUp()
	{
		for(UInt32 i=0; i<ROW_NINE; ++i)
		{
			const ATSudokuEngine::Cell* pCell = new ATSudokuEngine::Cell(i);
			aBlock_.Add(pCell);
			aBlock_.Set(i, i+1);
		}

		return True;
	}

	virtual Bool TearDown()
	{
		for(UInt32 i=0; i<ROW_NINE; ++i)
		{
			const ATSudokuEngine::Cell* pCell = aBlock_.At(i);
			delete pCell;
			pCell = NULL;
		}

		aBlock_.Clear();
		return True;
	}

	int TestRowBlock()
	{
		ATASSERT(ROW_NINE == aBlock_.Size());

		for(UInt32 i=0; i<ROW_NINE; ++i)
		{
			const ATSudokuEngine::Cell* pTemp = aBlock_.At(i);
			
			ATASSERT(pTemp->Value() == i+1);
		}

		return 0;
	}

	int TestModifyCellValue()
	{
		const UInt32 nIndex1 = 2;
		const UInt32 nIndex2 = 7;

		const UInt32 nValue1 = 8;
		const UInt32 nValue2 = 3;

		ATASSERT(aBlock_.Set(nIndex1, ATSudokuEngine::INVALID_VALUE));
		ATASSERT(aBlock_.Set(nIndex2, ATSudokuEngine::INVALID_VALUE));

		ATASSERT(aBlock_.Set(nIndex1, nValue1));
		ATASSERT(aBlock_.Set(nIndex2, nValue2));
		return 0;
	}

	/// check duplicated Cell's index in Block
	int TestDuplicatedIndex()
	{
		for(int i=0; i<ROW_NINE; ++i)
		{
			ATSudokuEngine::Cell aCell(i);
			
			// Can't add elements which has same Cell's index in a Block
			ATASSERT(ROW_NINE == aBlock_.Add(&aCell));
		}

		return 0;
	}

	/// find Cell object by Cell's index
	int TestFindCell()
	{
		UInt32 nCellIndex = 5;

		// aCell is casting to UInt32
		const ATSudokuEngine::Cell* pTemp1 = aBlock_.Find(nCellIndex);
		ATASSERT(*pTemp1 == nCellIndex);

		// if Block has't a Cell, return value was False and Cell has INVALID_VALUE
		nCellIndex = UINT_MAX;
		const ATSudokuEngine::Cell* pTemp2 = aBlock_.Find(nCellIndex);
		ATASSERT(pTemp2 == Null);

		return 0;
	}

	/// Check duplicated value
	int TestIsValid()
	{
		ATASSERT(aBlock_.IsValid());

		ATASSERT(False == aBlock_.Set(5, 3));

		ATASSERT(aBlock_.IsValid());
		return 0;
	}

protected:
	ATSudokuEngine::Block aBlock_;
};

#endif